package com.sbw.tinysoft.core.service.impl;

import com.sbw.tinysoft.Utils.ArticleSpider;
import com.sbw.tinysoft.Utils.TinyUtil;
import com.sbw.tinysoft.Utils.analyzer.impl.VisaIpMethodListDocumentAnalyzer;
import com.sbw.tinysoft.Utils.analyzer.impl.VisaMethodDayListDocumentAnalyzer;
import com.sbw.tinysoft.Utils.analyzer.impl.VisaServiceDayListDocumentAnalyzer;
import com.sbw.tinysoft.core.entity.Ip2Projects;
import com.sbw.tinysoft.core.entity.Method2Ips;
import com.sbw.tinysoft.core.entity.Service2Method;
import com.sbw.tinysoft.core.entity.VisaApi2Services;
import com.sbw.tinysoft.core.service.VisaService2ProjectsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 解析 visaApi与各项目调用关系
 * @Author: sangbowei
 * @Description: TODO
 * @Date: Created in  15:28 2017\12\6 0006
 **/
@Service
public class VisaService2ProjectsServiceImpl implements VisaService2ProjectsService {


    @Value("${servicePreurl}")
    private String servicePreUrl;

    @Value("${methodPreurl}")
    private String methodPreurl;

    @Value("${ipPreurl}")
    private String ipPreUrl;

    @Autowired
    RedisTemplate redisTemplate;

    @Resource
    private VisaServiceDayListDocumentAnalyzer serviceDayListDocumentAnalyzer;

    @Resource
    private VisaMethodDayListDocumentAnalyzer methodDayListDocumentAnalyzer;

    @Resource
    private VisaIpMethodListDocumentAnalyzer ipMethodListDocumentAnalyzer;

    @Override
    public VisaApi2Services parseVisaApiProjectsRelation() throws Exception {
        List<VisaApi2Services> visaApi2Services = ArticleSpider.forVisaApi2ServicesList(TinyUtil.serviceListUrl(servicePreUrl),serviceDayListDocumentAnalyzer,VisaApi2Services.class);
        VisaApi2Services api2Services = visaApi2Services.get(0);
        setServiceMethod(api2Services);
        return api2Services;
    }

    private void setServiceMethod(VisaApi2Services api2Service) throws Exception{
        if(null==api2Service){
            return;
        }

        List<Service2Method> service2Methods = new ArrayList<>();

        List<String> fullServiceList =  api2Service.getFullServices();
        for(String service:fullServiceList){
            service2Methods.add(findServiceMethod(service));
        }
        api2Service.setService2Methods(service2Methods);
    }

    /**
     * 获取接口的方法列表
     * @param serviceName
     * @return
     */
    private Service2Method findServiceMethod(String serviceName) throws Exception{
        List<Service2Method> service2MethodList = ArticleSpider.forService2MethodList(TinyUtil.methodListUrl(methodPreurl,serviceName),methodDayListDocumentAnalyzer,Service2Method.class);
        Service2Method service2Method = service2MethodList.get(0);
        setMethodIp(service2Method);
        fillServiceProjects(service2Method);
        return service2Method;
    }

    /**
     * 设置 service中被调用的projects
     * @param service2Method
     */
    private void fillServiceProjects(Service2Method service2Method){
        if(service2Method==null){
            return;
        }

        List<Method2Ips> method2Ips = service2Method.getMethod2Ips();
        if(CollectionUtils.isEmpty(method2Ips)){
            return;
        }

        Set<String> serviceProjects = new HashSet<>();
        for(Method2Ips method2Ips1:method2Ips){
            List<String> methodProjects = fillMethodProjects(method2Ips1);
            for(String methodProject:methodProjects ){
                serviceProjects.add(methodProject);
            }
        }
        service2Method.setProjects(serviceProjects);
    }

    /**
     * 设置 方法对应的被调用项目名称
     * @param method2Ips
     * @return
     */
    private List<String> fillMethodProjects(Method2Ips method2Ips){
        List<String> methodProjects = new ArrayList<>();
        if(null!=method2Ips){
            List<Ip2Projects> ip2ProjectsList = method2Ips.getIp2Projects();
            for(Ip2Projects ip2Projects:ip2ProjectsList){
                if(!CollectionUtils.isEmpty(ip2Projects.getProjects())){
                    methodProjects.addAll(ip2Projects.getProjects());
                }
            }
        }
        return methodProjects;
    }

    /**
     * 设置
     * @param service2Method
     * @throws Exception
     */
    private void setMethodIp(Service2Method service2Method) throws Exception{
        if(null==service2Method){
            return;
        }

        List<Method2Ips> method2Ips = new ArrayList<>();

        String serviceName = service2Method.getService();
        List<String> methods =  service2Method.getMethods();
        for(String method:methods){
            Method2Ips method2Ips_1 = findMethodIps(serviceName,method);
            if(null!=method2Ips_1){
                method2Ips.add(method2Ips_1);
            }
        }
        service2Method.setMethod2Ips(method2Ips);
    }

    /**
     * 获取方法对应的服务器Ips
     * @param serviceName
     * @return
     * @throws Exception
     */
    private Method2Ips findMethodIps(String serviceName,String methodName) throws Exception{
        List<Method2Ips> method2IpsList = ArticleSpider.forMethod2IpsList(TinyUtil.ipListUrl(ipPreUrl,serviceName,methodName),ipMethodListDocumentAnalyzer,Method2Ips.class);
        if(CollectionUtils.isEmpty(method2IpsList)){
            return null;
        }
        Method2Ips method2Ips = method2IpsList.get(0);
        setIpProjects(method2Ips);
        return method2Ips;
    }

    private void setIpProjects(Method2Ips method2Ip){
        if(null==method2Ip){
            return;
        }

        List<Ip2Projects> ip2Projects = new ArrayList<>();
        List<String> ipList = method2Ip.getIps();
        for(String ip:ipList){
            Ip2Projects ip2pro = new Ip2Projects();
            ip2pro.setIp(ip);
            ip2pro.setProjects(findProjectsByIp(ip));
            ip2Projects.add(ip2pro);
        }
        method2Ip.setIp2Projects(ip2Projects);
    }

    /**
     * 获取 ip对应的projects
     */
    private List<String> findProjectsByIp(String ip){
        List<String> projects = new ArrayList<>();
        if(!StringUtils.isEmpty(ip)){
            projects = (List<String>) redisTemplate.opsForValue().get(ip);
        }
        return projects;
    }
}
